/*
 * Copyright (c) 2013.
 * 游戏服务器核心代码编写人陈磊拥有使用权
 * 联系方式：E-mail:13638363871@163.com ;qq:502959937
 * 个人博客主页：http://my.oschina.net/chenleijava
 */

package com.dc.gameserver.serverCore.service.character;

import com.dc.gameserver.extComponents.utilsKit.util.random.Rnd;
import com.dc.gameserver.hardCode.CardType;
import com.dc.gameserver.hardCode.PkStatus;
import com.dc.gameserver.serverCore.model.gamemodel.LevelModel;
import com.dc.gameserver.serverCore.model.gamemodel.MonsterModel;
import com.dc.gameserver.serverCore.model.gamemodel.SkillModel;
import com.dc.gameserver.serverCore.model.gamemodel.script.ScriptFactory;
import com.dc.gameserver.serverCore.service.battle.GameFormula;
import com.dc.gameserver.serverCore.service.cardModule.Card;
import com.dc.gameserver.serverCore.service.cardModule.CardBox;
import javolution.util.FastTable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author 石头哥哥
 *         Date: 13-12-4</br>
 *         Time: 下午3:41</br>
 *         Package: com.dc.gameserver.serverCore.service.character</br>
 *         注解： 怪物对象 pve
 *         组装怪物
 */
public class Monster extends GameCharacter {

    private static final Logger LOGGER= LoggerFactory.getLogger(Monster.class);
    //如果技能编号为0，表示monster Model不拥有该技能
    private Integer skillID1;     //怪物技能编号 1
    private Integer skillID2;     //怪物技能编号 2
    private Integer skillID3;     //怪物技能编号 3
    private MonsterModel monsterModel;
    private LevelModel levelModel;
    FastTable<Integer> tempSillID;


    /**怪物获取card辅助容器*/
    FastTable<Card> tempCards=null;    //随机获取一种类型牌
    FastTable<Card> tempCardsList1=null;    //相同类型牌集合



    /**
     * 初始化怪物战斗信息
     * @param monsterModel  怪物model组装
     */
    public Monster(MonsterModel monsterModel,LevelModel levelModel){

        this.monsterModel=monsterModel;
        this.levelModel=levelModel;
        tempSillID=new FastTable<Integer>();
    }

    /**
     * 获取怪物技能随机值
     * @return   技能随机值
     */
    private int rndSkillID(){
        int size= tempSillID.size();
        --size;
        return tempSillID.get(Rnd.newInstance(Rnd.RandomType.UNSECURE_VOLATILE).getInt(0,size));
    }

    /**
     *
     * {@link com.dc.gameserver.serverCore.service.battle.GameFormula}
     * 组装怪物战斗信息 ,在服务器启动的时候实例化monster对象
     * blood
     * sheild
     * magic
     * attack
     * Defence
     * soual   神识判定
     * 在战斗之前，monster战斗各个属性都已初始化，且数据源来自配置
     */
    public void buildMonsterBattleInfo(){
        tempCards=new FastTable<Card>();
        tempCardsList1=new FastTable<Card>();

        setName(monsterModel.getMonsterName()); //monsterName
        setID(monsterModel.getId());  //monster ID

//        setMaxBlood(monsterModel.getMonsterMaxBlood()); //气血
//        setCurrentBlood(monsterModel.getMonsterMaxBlood());//气血

        setMaxShield(monsterModel.getMonsterMaxShiled()); //法术盾
        setCurrentShield(monsterModel.getMonsterMaxShiled());  //法术盾

        setMaxMagic(monsterModel.getMonsterMaxMagic());  //法力值
        setCurrentMagic(monsterModel.getMonsterMaxMagic());  //法力值


        setAttack(monsterModel.getMonsterAttack());   //攻击值
        setDefence(monsterModel.getMonsterDefence()); //防御值
        setRecoveryMagic(monsterModel.getMonsterRecoveryMagic());  //法力值恢复速度

        setMaxSual(monsterModel.getMonsterMaxSual());//怪物神识值  ，使用眩晕判定数据源
        setSoul(monsterModel.getMonsterMaxSual()); // only max soul


        //气势值上下限----判定monster出牌的点数规则
        setBaseMaxMomentum(monsterModel.getMonsterBaseMaxMomentum());
        setBaseMinMomentum(monsterModel.getMonsterBaseMinMomentum());
        this.setSelfFiveType(monsterModel.getFiveType());  //怪物自身五行属性


        setMinCount(getBaseMinMomentum());
        setMaxCount(getBaseMaxMomentum());


        setFangreduceMagic(monsterModel.getFangreduceMagic());
        setFangrecoverysheild(monsterModel.getFangrecoverysheild());



        /**
         * 怪物技能编号  如果当前怪物只有一个技能，这样是可行的，
         * 如果是多种技能，那么monster将会更加牌的类型来设定技能，
         * 从而觉得技能的五行需求值   ,添加怪物存在的技能
         * */
        int skillID1=monsterModel.getSkillID1();
        if (skillID1!=0){
            setSkillID1(skillID1);
            tempSillID.addFirst(skillID1);
            setFiveTypeSkillValue(GameFormula.fiveTypeSkillValue(levelModel, ScriptFactory.skillModelFastMap.get(skillID1)));
        }
        int skillID2=monsterModel.getSkillID2();
        if (skillID2!=0){
            setSkillID2(skillID2);
            tempSillID.addFirst(skillID2);
            setFiveTypeSkillValue(GameFormula.fiveTypeSkillValue(levelModel,ScriptFactory.skillModelFastMap.get(skillID2)));
        }
        int skillID3=monsterModel.getSkillID3();
        if (skillID3!=0){
            setSkillID3(skillID3);
            tempSillID.addFirst(skillID3);
            setFiveTypeSkillValue(GameFormula.fiveTypeSkillValue(levelModel,ScriptFactory.skillModelFastMap.get(skillID3)));
        }


        /**战斗变量设置*/
        setPkStatus(PkStatus.NO_PK);
        setFirstHand(false);  //PVE  role 为先手  monster   false
        setCardType(null);
        setCardBoxID(-1);
        setGiveOut(false);
        setDizzinessTimes(0);
        setOutCardsList(new FastTable<Card>());
        setCardlib(new FastTable<Card>());

    }

    /**
     * 回合结束
     * 销毁monster资源
     * @param cardBox
     */
    @Override
    public void clearPkResourceWithRoundOver(CardBox cardBox) {
        RecoverCard(cardBox);
        this.setCardBoxID(-1);
        this.setFirstHand(false);
        this.setActionOutCard(false);
        this.setGiveOut(false);

        this.setPkStatus(PkStatus.NO_PK);
        this.setDizzinessTimes(0);//眩晕 set  0
        this.getOutCardsList().clear();
        setCardlib(null);
        setOutCardsList(null);
        setCardType(null);
        tempSillID.clear();
        tempSillID=null;
        this.setMaxHoldCard(0);
        this.tempCards.clear();
        this.tempCards=null;
        this.tempCardsList1.clear();
        this.tempCardsList1=null;
    }

    /**
     * 添加系统分发的纸牌对象列表
     *
     * @param disCardList 系统分发的纸牌对象列表
     */
    @Override
    public void add(Card[] disCardList) {
        FastTable<Card> cards=getCardlib();
        cards.addAll(disCardList);
        cards.sort();    //快速排序
    }

    /**
     * 添加出牌对象到预出牌区列表对象 outCardsList
     *
     * @param card
     */
    @Override
    public void addOutCard(Card card) {
        this.getOutCardsList().addLast(card);
    }

    /**
     * 当前回合结束，清除当前回合中的资源，重置，准备下一次回合资源
     */
    @Override
    public void clearRoundResource() {
        if (!this.getOutCardsList().isEmpty()){
            this.recoverRoundCard();   //回收
        }
        this.setGiveOut(false);
    }

    /**
     * 清除资源 离开pk状态   ，当下次回合开始，再次组装怪物对象
     * 销毁monster资源对象
     */
    @Override
    public void clearAllResourceOutOfPK(CardBox cardBox) {
        RecoverCard(cardBox);
        this.setCardBoxID(-1);
        this.setPkStatus(PkStatus.NO_PK);
        this.setDizzinessTimes(0);
        this.setOutCardsList(null);
        this.setCardlib(null);
        setPkStatus(null);
        setCardType(null);
        setFirstHand(false);
        setActionOutCard(false);
        this.setMaxHoldCard(0);
        this.tempCards.clear();
        this.tempCards=null;
        this.tempCardsList1.clear();
        this.tempCardsList1=null;
    }

    public static void main(String[]args){
        System.out.println(Rnd.newInstance(Rnd.RandomType.UNSECURE_VOLATILE).getInt(0,0));
    }


    /**
     * monster 出牌规则 AI  注意保持出牌的合法性
     *  1.Config.DEFAULT_VALUE.GAME_VALUE.maxOutCards 出牌张数
     *  2.出牌类型；          神识 -> 防御 -> 攻击 -> 技能             1,2,3,4
     *  3.出技能 防御牌 法力值是否足够；
     * @return       FastTable<Card>
     */
    public FastTable<Card> monsterOutCards(){

       FastTable<Card> cards=this.getCardlib();
        /**
         * 1.如果所有牌是技能或则防御牌构成，且没有蓝可用，那么monster就放弃出牌
         * 2.玩家回合超时未出牌，AI 自动出牌
         */
       try {
           for (;;){
               //只有技能或则只有防牌或则只有技能和防牌 ；（神识，攻击）
               if (this.getCurrentMagic()==0){
                   boolean only=true;
                   //神识 -> 防御 -> 攻击 -> 技能
                   // 1   >   2   >   3  >   4
                   for (Card card:cards){
                       if (card.getType()== 0x1 ||card.getType()== 0x4){
                           only=false;
                           break;
                       }
                   }
                   if (only){
                       return null;
                   }
               }
               int cardLibSize=cards.size();//牌库不可能为null
               if (cardLibSize!=0){
                   int index= Rnd.newInstance(Rnd.RandomType.UNSECURE_VOLATILE).getInt(0,cardLibSize-1);
                   Card card =cards.get(index);  //
                   if (card==null)continue;
                   CardType cardType=CardType.getTypeByFlg(card.getType());
                   int maxOutCardNum=this.getMaxOutCard();
                   for (Card c:cards){
                       LOGGER.debug("card type and num："+c.getType()+":"+c.getCount());
                       if (c.getType()==cardType.getType()){
                           tempCardsList1.addLast(c);
                       }
                       if (tempCardsList1.size()==maxOutCardNum)break;
                   }

                   //获取的牌数量最多等于最大出牌数量
                   if (cardType.getType()==CardType.MAGIC_TYPE.getType()){
                       //技能牌类型
                       int skillID=rndSkillID();
                       this.setBattleSkillID(skillID);
                       SkillModel skillModel=ScriptFactory.skillModelFastMap.get(skillID);
                       this.setSkillfiveType(skillModel.getElement());  //
                       this.setReduceMagic(skillModel.getReduceMagic());//出技能牌消耗技能
                       //计算monster出技能 将会消耗的法力值 ，使用技能牌和出牌的数量无关
                       int magic= GameFormula.computeMagicUse(this);
                       if (this.getCurrentMagic()<magic){
                           tempCards.addAll(tempCardsList1);//add to temp ,if success ,will be return to cards
                           cards.removeAll(tempCardsList1);  //移除技能牌类型
                           tempCardsList1.clear();
                           continue;
                       }else{
                           // 移除牌库数据
                           for (Card cc:tempCardsList1){
                               cards.remove(cc);
                           }
                           //设置出牌类型
                           this.setCardType(cardType);
                           return tempCardsList1;
                       }
                   }

                   //防御牌类型
                   if (cardType.getType()==CardType.DEFENCE_TYPE.getType()){
                       int t1_size=tempCardsList1.size();
                       //防牌消耗的法力值和牌的张数有关
                       int maxMagic= GameFormula.ComputeDeffenceLoss(this,t1_size);
                       int minMagic=GameFormula.ComputeDeffenceLoss(this, 0x1);//一张牌消耗的法力值
                       int currentMagic=this.getCurrentMagic();

                       if (minMagic==maxMagic){   //只有一张牌
                           if (currentMagic>maxMagic){
                               // 移除牌库数据
                               for (Card cc:tempCardsList1){
                                   cards.remove(cc);
                               }
                               //设置出牌类型
                               this.setCardType(cardType);
                               return tempCardsList1;
                           }else {
                               tempCards.addAll(tempCardsList1);//add to temp ,if success ,will be return to cards
                               cards.removeAll(tempCardsList1);  //移除防御牌类型  next time 不会再取出防御牌
                               tempCardsList1.clear();
                               continue;
                           }
                       }else {
                           //minMagic~~maxMagic
                           if (currentMagic<minMagic){
                               tempCards.addAll(tempCardsList1);//add to temp ,if success ,will be return to cards
                               cards.removeAll(tempCardsList1);  //移除防御牌类型  next time 不会再取出防御牌
                               tempCardsList1.clear();
                               continue;
                           }
                           if (currentMagic>=minMagic&&currentMagic<maxMagic){
                               //出一张牌
                               for (;;){
                                   tempCardsList1.pollLast();  //从出牌队列中移除
                                   if (tempCardsList1.size()==1)break;
                               }
                               //移除牌库类型牌
                               cards.remove(tempCardsList1.getLast());
                               //设置出牌类型
                               this.setCardType(cardType);
                               return tempCardsList1;
                           }else {
                               // CurrentMagic>=magic
                               // 移除牌库数据
                               for (Card cc:tempCardsList1){
                                   cards.remove(cc);
                               }
                               //设置出牌类型
                               this.setCardType(cardType);
                               return tempCardsList1;
                           }
                       }
                   }

                   //神识 攻击 类型牌
                   // 移除牌库数据
                   for (Card cc:tempCardsList1){
                       cards.remove(cc);
                   }
                   //设置出牌类型
                   this.setCardType(cardType);
                   return tempCardsList1;
               } else {
                   //没有找到合适的牌类型，返回
                  return null;
               }
           }
       }finally {
           //if not empty ,return card to card lib   没有找到合适的牌类型，返回 回收cards
           if (tempCards.size()!=0){
               cards.addAll(tempCards);
               tempCards.clear();
           }
       }
    }


    public Integer getSkillID1() {
        return skillID1;
    }

    public void setSkillID1(Integer skillID1) {
        this.skillID1 = skillID1;
    }

    public Integer getSkillID2() {
        return skillID2;
    }

    public void setSkillID2(Integer skillID2) {
        this.skillID2 = skillID2;
    }

    public Integer getSkillID3() {
        return skillID3;
    }

    public void setSkillID3(Integer skillID3) {
        this.skillID3 = skillID3;
    }

}
